package org.dynobjects.core;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.jci.stores.ResourceStore;
import org.apache.commons.lang.StringUtils;

public class EPClassLoader extends ClassLoader {

	private static Map mapClasses = new HashMap();

	private static EPClassLoader classLoader;

	private ClassLoader parent = null;

	private String[] resources;

	private ResourceStore store;

	private EPClassLoader(ClassLoader parent) {
		super(parent);
		this.parent = parent;
	}

	public static final EPClassLoader getInstance() {
		if (classLoader == null) {
			classLoader = new EPClassLoader(EPClassLoader.class
					.getClassLoader());
		}
		return classLoader;
	}

	public Class findClass(byte[] bs, String className)
			throws ClassNotFoundException {

		byte[] byteCode = (byte[]) mapClasses.get(className);
		Class returnValue = null;
		if (byteCode == null) {
			returnValue = defineClass(className, bs, 0, bs.length);
			mapClasses.put(className, bs);
		}
		return returnValue;
	}

	public Class get(String name) throws ClassNotFoundException {
		byte[] byteCode = (byte[]) mapClasses.get(name);

		return defineClass(name, byteCode, 0, byteCode.length);
	}

	protected synchronized Class loadClass(String name, boolean resolve)
			throws ClassNotFoundException {
		Class c = findLoadedClass(name);
		if (c == null) {
			try {
				c = findSystemClass(name);
			} catch (Exception e) {
			}
			if (c == null) {
				for (int i = 0; i < resources.length; i++) {
					String string = resources[i];
					String _classResource = StringUtils.replace(string,
							".java", ".class");

					String qualifiedClassName = StringUtils.replace(
							_classResource, ".class", "");
					qualifiedClassName = StringUtils.replaceChars(
							qualifiedClassName, "/", ".");
					c = classLoader.findClass(store.read(_classResource),
							qualifiedClassName);
				}
			}
		}
		if(resolve){
			resolveClass(c);
		}

		return c;
	}

	public void setResources(String[] resources) {
		this.resources = resources;
	}

	public void setStore(ResourceStore store) {
		this.store=store;
	}

}
